<template>
  <div class="home" style="margin: 1vw">
    <Button type="success" @click="getPermission()" style="margin: 1vw"
      >获取麦克风权限</Button
    >
    <br />
    <Button type="info" @click="startRecorder()" style="margin: 1vw"
      >开始录音</Button
    >
    <Button type="info" @click="resumeRecorder()" style="margin: 1vw"
      >继续录音</Button
    >
    <Button type="info" @click="pauseRecorder()" style="margin: 1vw"
      >暂停录音</Button
    >
    <Button type="info" @click="stopRecorder()" style="margin: 1vw"
      >结束录音</Button
    >
    <br />
    <Button type="success" @click="playRecorder()" style="margin: 1vw"
      >录音播放</Button
    >
    <Button type="success" @click="pausePlayRecorder()" style="margin: 1vw"
      >暂停录音播放</Button
    >
    <Button type="success" @click="resumePlayRecorder()" style="margin: 1vw"
      >恢复录音播放</Button
    >
    <Button type="success" @click="stopPlayRecorder()" style="margin: 1vw"
      >停止录音播放</Button
    >
    <br />
    <Button type="info" @click="getRecorder()" style="margin: 1vw"
      >获取录音信息</Button
    >
    <Button type="info" @click="downPCM()" style="margin: 1vw">下载PCM</Button>
    <Button type="info" @click="downWAV()" style="margin: 1vw">下载WAV</Button>
    <Button type="info" @click="getMp3Data()" style="margin: 1vw"
      >下载MP3</Button
    >
    <br />
    <Button type="error" @click="destroyRecorder()" style="margin: 1vw"
      >销毁录音</Button
    >
    <br />
    <div style="width: 100%; height: 200px; border: 1px solid red">
      <canvas id="canvas"></canvas>
      <span style="padding: 0 10%"></span>
      <canvas id="playChart"></canvas>
    </div>
  </div>
</template>
<script>
import Recorder from "js-audio-recorder";
const lamejs = require("lamejs");
const recorder = new Recorder({
  sampleBits: 16, // 采样位数，支持 8 或 16，默认是16
  sampleRate: 48000, // 采样率，支持 11025、16000、22050、24000、44100、48000，根据浏览器默认值，我的chrome是48000
  numChannels: 1, // 声道，支持 1 或 2， 默认是1
  // compiling: false,(0.x版本中生效,1.x增加中)  // 是否边录边转换，默认是false
});
export default {
  data() {
    return {
      drawRecordId: null,
      oCanvas: null,
      ctx: null,
      //波浪图-播放
      drawPlayId: null,
      pCanvas: null,
      pCtx: null,
    };
  },
  mounted() {
    this.startCanvas();
  },
  methods: {
    startCanvas() {
      //录音波浪
      this.oCanvas = document.getElementById("canvas");
      this.ctx = this.oCanvas.getContext("2d");
      //播放波浪
      this.pCanvas = document.getElementById("playChart");
      this.pCtx = this.pCanvas.getContext("2d");
    },

    /**
     *  录音的具体操作功能
     * */
    // 开始录音
    startRecorder() {
      recorder.start().then(
        () => {
          this.drawRecord(); //开始绘制图片
        },
        (error) => {
          // 出错了
          console.log(`${error.name} : ${error.message}`);
        }
      );
    },
    // 继续录音
    resumeRecorder() {
      recorder.resume();
    },
    // 暂停录音
    pauseRecorder() {
      recorder.pause();
      this.drawRecordId && cancelAnimationFrame(this.drawRecordId);
      this.drawRecordId = null;
    },
    // 结束录音
    stopRecorder() {
      recorder.stop();
      this.drawRecordId && cancelAnimationFrame(this.drawRecordId);
      this.drawRecordId = null;
    },
    // 录音播放
    playRecorder() {
      recorder.play();
      this.drawPlay(); //绘制波浪图
    },
    // 暂停录音播放
    pausePlayRecorder() {
      recorder.pausePlay();
    },
    // 恢复录音播放
    resumePlayRecorder() {
      recorder.resumePlay();
      this.drawPlay(); //绘制波浪图
    },
    // 停止录音播放
    stopPlayRecorder() {
      recorder.stopPlay();
    },
    // 销毁录音
    destroyRecorder() {
      recorder.destroy().then(function () {
        recorder = null;
        this.drawRecordId && cancelAnimationFrame(this.drawRecordId);
        this.drawRecordId = null;
      });
    },
    /**
     *  获取录音文件
     * */
    getRecorder() {
      let toltime = recorder.duration; //录音总时长
      let fileSize = recorder.fileSize; //录音总大小

      //录音结束，获取取录音数据
      let PCMBlob = recorder.getPCMBlob(); //获取 PCM 数据
      let wav = recorder.getWAVBlob(); //获取 WAV 数据

      let channel = recorder.getChannelData(); //获取左声道和右声道音频数据
    },
    /**
     *  下载录音文件
     * */
    //下载pcm
    downPCM() {
      //这里传参进去的时文件名
      recorder.downloadPCM("新文件");
    },
    //下载wav
    downWAV() {
      //这里传参进去的时文件名
      recorder.downloadWAV("新文件");
    },
    /**
     *  获取麦克风权限
     * */
    getPermission() {
      Recorder.getPermission().then(
        () => {
          this.$toast.success("获取权限成功");
        },
        (error) => {
          console.log(`${error.name} : ${error.message}`);
        }
      );
    },
    /**
     * 文件格式转换 wav-map3
     * */
    getMp3Data() {
      const mp3Blob = this.convertToMp3(recorder.getWAV());
      var formData = new FormData();
      var fileOfBlob = new File([mp3Blob], new Date().getTime() + ".mp3", {
        type: "audio/mp3",
      });

      formData.append("test", fileOfBlob);

      this.$axios
        .post("http://139.196.93.237:3000/upload/img", formData)
        .then(
          function (response) {
            console.log(response);
          },
          function (err) {}
        )
        .catch(function (err) {});
      //   recorder.download(mp3Blob, "recorder", "mp3");
    },
    convertToMp3(wavDataView) {
      // 获取wav头信息
      const wav = lamejs.WavHeader.readHeader(wavDataView); // 此处其实可以不用去读wav头信息，毕竟有对应的config配置
      const { channels, sampleRate } = wav;
      const mp3enc = new lamejs.Mp3Encoder(channels, sampleRate, 128);
      // 获取左右通道数据
      const result = recorder.getChannelData();
      const buffer = [];

      const leftData =
        result.left &&
        new Int16Array(result.left.buffer, 0, result.left.byteLength / 2);
      const rightData =
        result.right &&
        new Int16Array(result.right.buffer, 0, result.right.byteLength / 2);
      const remaining = leftData.length + (rightData ? rightData.length : 0);

      const maxSamples = 1152;
      for (let i = 0; i < remaining; i += maxSamples) {
        const left = leftData.subarray(i, i + maxSamples);
        let right = null;
        let mp3buf = null;

        if (channels === 2) {
          right = rightData.subarray(i, i + maxSamples);
          mp3buf = mp3enc.encodeBuffer(left, right);
        } else {
          mp3buf = mp3enc.encodeBuffer(left);
        }

        if (mp3buf.length > 0) {
          buffer.push(mp3buf);
        }
      }

      const enc = mp3enc.flush();

      if (enc.length > 0) {
        buffer.push(enc);
      }

      return new Blob(buffer, { type: "audio/mp3" });
    },

    /**
     * 绘制波浪图-录音
     * */
    drawRecord() {
      // 用requestAnimationFrame稳定60fps绘制
      this.drawRecordId = requestAnimationFrame(this.drawRecord);

      // 实时获取音频大小数据
      let dataArray = recorder.getRecordAnalyseData(),
        bufferLength = dataArray.length;

      // 填充背景色
      this.ctx.fillStyle = "rgb(200, 200, 200)";
      this.ctx.fillRect(0, 0, this.oCanvas.width, this.oCanvas.height);

      // 设定波形绘制颜色
      this.ctx.lineWidth = 2;
      this.ctx.strokeStyle = "rgb(0, 0, 0)";

      this.ctx.beginPath();

      var sliceWidth = (this.oCanvas.width * 1.0) / bufferLength, // 一个点占多少位置，共有bufferLength个点要绘制
        x = 0; // 绘制点的x轴位置

      for (var i = 0; i < bufferLength; i++) {
        var v = dataArray[i] / 128.0;
        var y = (v * this.oCanvas.height) / 2;

        if (i === 0) {
          // 第一个点
          this.ctx.moveTo(x, y);
        } else {
          // 剩余的点
          this.ctx.lineTo(x, y);
        }
        // 依次平移，绘制所有点
        x += sliceWidth;
      }

      this.ctx.lineTo(this.oCanvas.width, this.oCanvas.height / 2);
      this.ctx.stroke();
    },
    /**
     * 绘制波浪图-播放
     * */
    drawPlay() {
      // 用requestAnimationFrame稳定60fps绘制
      this.drawPlayId = requestAnimationFrame(this.drawPlay);

      // 实时获取音频大小数据
      let dataArray = recorder.getPlayAnalyseData(),
        bufferLength = dataArray.length;

      // 填充背景色
      this.pCtx.fillStyle = "rgb(200, 200, 200)";
      this.pCtx.fillRect(0, 0, this.pCanvas.width, this.pCanvas.height);

      // 设定波形绘制颜色
      this.pCtx.lineWidth = 2;
      this.pCtx.strokeStyle = "rgb(0, 0, 0)";

      this.pCtx.beginPath();

      var sliceWidth = (this.pCanvas.width * 1.0) / bufferLength, // 一个点占多少位置，共有bufferLength个点要绘制
        x = 0; // 绘制点的x轴位置

      for (var i = 0; i < bufferLength; i++) {
        var v = dataArray[i] / 128.0;
        var y = (v * this.pCanvas.height) / 2;

        if (i === 0) {
          // 第一个点
          this.pCtx.moveTo(x, y);
        } else {
          // 剩余的点
          this.pCtx.lineTo(x, y);
        }
        // 依次平移，绘制所有点
        x += sliceWidth;
      }

      this.pCtx.lineTo(this.pCanvas.width, this.pCanvas.height / 2);
      this.pCtx.stroke();
    },
  },
};
</script>